package org.bdware.repository.webService.service;

import com.google.gson.JsonArray;
import org.apache.log4j.Logger;
import org.bdware.doip.core.doipMessage.DoipMessage;
import org.bdware.doip.core.doipMessage.DoipMessageFactory;
import org.bdware.doip.core.doipMessage.DoipResponseCode;
import org.bdware.doip.core.doipMessage.MessageCredential;
import org.bdware.doip.core.exception.DoDecodeException;
import org.bdware.doip.core.model.digitalObject.DigitalObject;
import org.bdware.doip.core.model.metadata.SearchParameter;
import org.bdware.doip.core.model.operations.BasicOperations;
import org.bdware.doip.endpoint.doipServer.DoipServiceInfo;
import org.bdware.repository.handler.BDRepositoryHandler;
import org.bdware.repository.main.BDRepository;
import org.bdware.repository.storage.BDRepoStorage;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;

@Service
public class DigitalObjectService {

    BDRepositoryHandler handler = BDRepository.getRepositoryHandler();
    DoipServiceInfo doipInfo = BDRepository.getInfo();
    BDRepoStorage store = BDRepository.getStore();

    static Logger logger = Logger.getLogger(DigitalObjectService.class);

    public DigitalObjectService() throws InterruptedException {
        int count = 0;
        while(handler == null || doipInfo == null){
            logger.info("wait for DOIP Service initialization");
            Thread.sleep(1000);
            if(count++>5) break;
        }
        if(handler == null || doipInfo == null){
            logger.error("DOIP Service not initialized.");
        }
    }

    public String storeDO(DigitalObject digitalObject, String userID){
        DoipMessage msg =
                new DoipMessageFactory.DoipMessageBuilder()
                        .createRequest(doipInfo.id, BasicOperations.Create.getName())
                        .setBody(digitalObject)
                        .create();
        msg.credential = new MessageCredential(userID);
        DoipMessage resp = handler.handleCreate(msg);
        if(resp.header.parameters.response != DoipResponseCode.Success){
            logger.info("create DO failed: " + resp.header.parameters.response.getName());
            logger.info("msg body: " + resp.body.getDataAsJsonString());
            return resp.header.parameters.response.getName();
        }
        try {
            logger.info("create DO: " + resp.body.getDataAsDigitalObject().toString());
            return resp.body.getDataAsDigitalObject().toString();
        }catch (Exception e){
            logger.info("create DO: " + resp.body.getDataAsJsonString());
            return resp.body.getDataAsJsonString();
        }
    }

    public JsonArray getDOListByUserID(String userID){
        return store.getDOsByUserID(userID);
    }

    public HashMap<String,JsonArray> getAllDOListGroupByUserID(){
        return store.getUserStats();
    }

    public DigitalObject getDOByID(String doID){

        DoipMessage msg =
                new DoipMessageFactory.DoipMessageBuilder()
                        .createRequest(doID,BasicOperations.Retrieve.getName())
                        .create();
        msg.header.parameters.addAttribute("includeElementData", true);
        DoipMessage resp = handler.handleRetrieve(msg);
        if(resp.header.parameters.response != DoipResponseCode.Success){
            logger.info("retrieve DO failed: " + resp.header.parameters.response.getName());
//            logger.info("msg body: " + resp.body.getDataAsJsonString());
        }else {
            logger.info("retrieve success: " + doID);
//            logger.info(resp.body.getDataAsJsonString());
            try {
                return resp.body.getDataAsDigitalObject();
            } catch (DoDecodeException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
        //return store.getDoByID(doID);
    }

    public boolean deleteDOByID(String doID,String userID){
        DoipMessage msg =
                new DoipMessageFactory.DoipMessageBuilder()
                        .createRequest(doID,BasicOperations.Delete.getName())
                        .create();
        msg.credential = new MessageCredential(userID);
        DoipMessage resp = handler.handleDelete(msg);
        if(resp.header.parameters.response != DoipResponseCode.Success){
            logger.info("create DO failed: " + resp.header.parameters.response.getName());
            logger.info("msg body: " + resp.body.getDataAsJsonString());
            return false;
        }else {
            logger.info("delete success: " + doID);
            logger.info("user: " + userID);
            return true;
        }
    }

    public String search(String query, int size){
        SearchParameter sp = SearchParameter.getDefaultParameter();
        sp.query = query;
        sp.type = "full";
        sp.pageNum = 1;
        sp.pageSize = size;
        DoipMessage msg =
                new DoipMessageFactory.DoipMessageBuilder()
                        .createRequest(doipInfo.id,BasicOperations.Search.getName())
                        .addAttributes("query",sp.query)
                        .addAttributes("pageNum",sp.pageNum)
                        .addAttributes("pageSize",sp.pageSize)
                        .addAttributes("type",sp.type)
                        .addAttributes("sortFields",sp.sortFieldsSer)
                        .create();
        DoipMessage resp = handler.handleSearch(msg);
        return resp.body.getDataAsJsonString();
    }
}
